
/* copyright (c) 1996, 1997, 1998, 1999 William R. Pearson and the
   U. of Virginia */

/* $Name: fasta34t11d4 $ - $Id: showbest.c,v 1.27 2002/04/14 02:48:01 wrp Exp $ */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "defs.h"
#include "mm_file.h"

#ifndef PCOMPLIB
#include "mw.h"
#else
#include "p_mw.h"
#endif

#include "structs.h"
#include "param.h"

extern int (*ranlib) (char *str, int cnt,
	       FSEEK_T libpos, char *libstr,
	       struct lmf_str *lm_fd);

#define RANLIB (m_fptr->ranlib)

#define MAX_BLINE 200

int
re_getlib(unsigned char *, int, int, int, int, long *, long *, 
	  struct lmf_str *m_fptr);

extern void do_opt (unsigned char *aa0, int n0, unsigned char *aa1, int n1,
		    int frame, struct pstruct *pst, void *f_str,
		    struct rstruct *rst);

int calc_id(const unsigned char *aa0, const int n0,
	    const unsigned char *aa1, const int n1,
	    int *res, int nres,
	    struct a_struct *aln, struct pstruct pst,
	    void *f_str);

void cal_coord(int n0, int n1, long sq0off, long loffset,
	       struct a_struct *aln);

extern int do_walign(unsigned char *aa0, int n0,
		     unsigned char *aa1, int n1, int frame,
		     struct pstruct *ppst, void *f_str,
		     int **res, int *nres, struct a_struct *aln);

struct lmf_str *re_openlib(struct lmf_str *, int outtty);

extern double zs_to_bit(float, int, int);

void showbest (FILE *fp, unsigned char **aa0, unsigned char *aa1, int maxn,
	       struct beststr **bptr,int nbest, int qlib, struct mngmsg *m_msg,
	       struct pstruct pst, struct db_str db,
	       void **f_str,char *gstring2)
{
  int ntmp = 0;
  char bline[MAX_BLINE], fmt[40], pad[MAX_BLINE], rline[40];
  char l_name[128];
  int istart = 0, istop, ib;
  int nshow;
  int quiet;
  int r_margin;
  struct beststr *bbp;
  int n1tot;
  char *bp;
  char rel_label[12];
  char tmp_str[20];
  long loffset, l_off;
  int n0, n1;
  struct rstruct rst;
  int *res, nres, sw_score, lc, maxc, nident, ngap;
  float percent, gpercent;
  struct lmf_str *m_fptr;

  strncpy(rel_label,"\0",2);
#ifdef SHOWREL
  strncpy(rel_label," related",sizeof(rel_label));
#endif
#ifdef SHOWUN
  strncpy(rel_label," unrelated",sizeof(rel_label));
#endif
  rel_label[sizeof(rel_label)-1]='\0';

#ifdef PCOMPLIB
  quiet = 1;
#else
  quiet = m_msg->quiet;
#endif

  n0 = m_msg->n0;

  if (m_msg->aln.llen > MAX_BLINE) m_msg->aln.llen = MAX_BLINE;

  if (pst.zsflag < 0) r_margin = 10;
  else if (pst.zsflag>=0  && m_msg->srelv > 1 ) r_margin = 19;
  else r_margin = 10;

  if (m_msg->nframe < 0) 
#ifndef SUPERFAMNUM
    sprintf(fmt,"%%-%ds (%%4d)",m_msg->aln.llen-r_margin);
#else
    sprintf(fmt,"%%-%ds [%%4d](%%4d)",m_msg->aln.llen-(r_margin+4));
#endif
  else 
    sprintf(fmt,"%%-%ds (%%4d)",m_msg->aln.llen-(r_margin+4));

  memset(pad,' ',m_msg->aln.llen-(r_margin+6));
  pad[m_msg->aln.llen-(r_margin+12)]='\0';

  if (quiet != -1) {
    nshow = 20;
    if (m_msg->mshow == -1) nshow = nbest;		/* show all */
    /* show specified number */
    else if (m_msg->mshow_flg) {
      nshow = min (m_msg->mshow, nshow);
    }
  }
  else nshow = m_msg->nshow;

  if (quiet==0) istop = 20;
  else istop = nshow;

  if (quiet==0) {
    printf(" How many scores would you like to see? [%d] ",m_msg->nshow);
    fflush(stdout);
    if (fgets(rline,20,stdin)==NULL) exit(0);
    nshow = m_msg->nshow;
    if (rline[0]!='\n' && rline[0]!=0) sscanf(rline,"%d",&nshow);
    if (nshow<=0) nshow = min(20,nbest);
  }

  if ((bp = strchr (m_msg->libstr, '\n')) != NULL) *bp = '\0';
/*   fprintf (fp, "%3d %s\n", qlib,m_msg->libstr); */

  if (m_msg->markx == 6) fprintf(fp,"<p><tt><pre>\n");

  if (pst.zsflag >= 0) {
    if (bptr[0]->escore < m_msg->e_cut) {
      if (m_msg->z_bits==1) {/* show bit score */
	fprintf(fp,"The best%s scores are:%s%s bits E(%ld)",
	       rel_label,pad,m_msg->label,pst.zdb_size);
      }
      else {/* show z-score */
	fprintf(fp,"The best%s scores are:%s%s z-sc E(%ld)",
	      rel_label,pad,m_msg->label,pst.zdb_size);
      }
      if (m_msg->markx==9)
	fprintf(fp,"\t%%_id  %%_gid %4s  alen  an0  ax0  pn0  px0  an1  ax1 pn1 px1 gapq gapl  fs ",m_msg->f_id1);
      fprintf(fp,"\n");
    }
    else {
      fprintf(fp,"!! No library sequences with E() < %.2g\n",m_msg->e_cut);
      m_msg->nshow = 0;
      if (m_msg->markx == 6) fprintf(fp,"<p></tt></pre>\n");
      return;
    }
  }
  else {
    fprintf(fp,"The best%s scores are:%s%s",rel_label,pad,m_msg->label);
    if (m_msg->markx==9)
      fprintf(fp,"\t%%_id  %%_gid %4s alen  an0  ax0  pn0  px0  an1  ax1  px0  px1  g_q g_l fs",m_msg->f_id1);
    fprintf(fp,"\n");
  }

  istart = 0;
l1:
  istop = min(nbest,nshow);
  for (ib=istart; ib<istop; ib++) {
    bbp = bptr[ib];
#ifdef SUPERFAMNUM
    if (bbp->nsfnum > 0 && sfn_cmp(m_msg->qsfnum_n,bbp->sfnum)) continue;
#ifdef SHOWUN
    if (bbp->nsfnum > 0 && sfn_cmp(m_msg->qsfnum,bbp->sfnum)) {
      istop = min(istop+1,nbest);
    /*
      fprintf(stderr,"skipping %d: %d==%d\n",ib,m_msg->qsfnum,bbp->sfnum);
      */
      continue;
    }
#endif
#ifdef SHOWREL
    if (bbp->nsfnum == 0 || (bbp->nsfnum > 0 && !sfn_cmp(m_msg->qsfnum,bbp->sfnum))) {
      istop = min(istop+1,nbest);
    /*
      fprintf(stderr,"skipping %d: %d==%d\n",ib,m_msg->qsfnum,bbp->sfnum);
      */
      continue;
    }
#endif
#endif
    if (quiet==1 && pst.zsflag>=0) {
      if (bbp->escore > m_msg->e_cut) {
	nshow = ib;
	goto done;
      }
      else if (bbp->escore < m_msg->e_low) continue;
    }

#ifndef PCOMPLIB
    if ((m_fptr=re_openlib(bbp->m_file_p,!m_msg->quiet))==NULL) {
      fprintf(stderr,"*** cannot re-open %s\n",bbp->m_file_p->lb_name);
      exit(1);
    }
    RANLIB(bline,m_msg->aln.llen-(r_margin),bbp->lseek,bbp->libstr,m_fptr);
#else
  strncpy(bline,bbp->desptr->bline,m_msg->aln.llen-r_margin);
  bline[m_msg->aln.llen-r_margin-1]='\0';
#endif

  /* l_name is used to build an HTML link from the bestscore line to
     the alignment.  It can also be used to discriminate multiple hits
     from the same long sequence.  This requires that fast_pan use -m 6. */

  strncpy(l_name,bline,sizeof(l_name)); /* get rid of text after second "|" */
  l_name[sizeof(l_name)-1]='\0';
  if ((bp=strchr(l_name,' '))!=NULL) *bp=0;
  if ((bp=strchr(&l_name[3],'|'))!=NULL) *bp='\0';
  if (m_msg->nframe > 2) sprintf(&l_name[strlen(l_name)],"_%d",bbp->frame+1);
  else if (m_msg->nframe > 0 && bbp->frame == 1)
    strncat(l_name,"_r",sizeof(l_name));
  if (bbp->cont-1 > 0) {
    sprintf(tmp_str,":%d",bbp->cont-1);
    strncat(l_name,tmp_str,sizeof(l_name));
  }

#ifndef SUPERFAMNUM
  bline[m_msg->aln.llen-r_margin]='\0';
#else
  bline[m_msg->aln.llen-r_margin-5]='\0';
#endif
  if (m_msg->stages>1 || m_msg->markx==9) {

    n1 = re_getlib(aa1,maxn,m_msg->maxt3,m_msg->loff,bbp->cont,&loffset,&l_off,bbp->m_file_p);

    if (m_msg->markx != 9) {
      do_opt (aa0[bbp->frame], n0, aa1, n1, bbp->frame, &pst, f_str[bbp->frame], &rst);
      bbp->score[2]=rst.score[2];
    }
    else {
      sw_score=
	do_walign(aa0[bbp->frame],m_msg->n0, aa1, n1, bbp->frame, 
		  &pst, f_str[bbp->frame], &res, &nres, &m_msg->aln);

      maxc = nres + 4*m_msg->aln.llen+4;

      lc=calc_id(aa0[bbp->frame],n0,aa1,n1,res,nres,
		 &m_msg->aln,pst,f_str[bbp->frame]);

      nident = m_msg->aln.nident;
      if (lc > 0) percent = (100.0*(float)nident)/(float)lc;
      else percent = -1.00;

      ngap = m_msg->aln.ngap_q + m_msg->aln.ngap_l;
      if (lc-ngap > 0) gpercent = (100.0*(float)nident)/(float)(lc-ngap);
      else gpercent = -1.00;

      cal_coord(n0,n1,m_msg->sq0off,loffset+l_off-1,&m_msg->aln);
    }
  }

  n1tot = (bbp->n1tot_p) ? *bbp->n1tot_p : bbp->n1;

  if (m_msg->nframe == -1) bline[m_msg->aln.llen-r_margin]='\0';
  else bline[m_msg->aln.llen-(r_margin+4)]='\0';

#ifndef SUPERFAMNUM
  fprintf (fp, fmt,bp=bline,n1tot);
#else
  if (m_msg->nframe == -1)
    fprintf (fp, fmt,bp=bline,bbp->sfnum[0],n1tot);
  else fprintf (fp, fmt,bp=bline,n1tot);
#endif

  if (m_msg->nframe > 2) fprintf (fp, " [%d]", bbp->frame+1);
  else if (m_msg->nframe >= 0) fprintf(fp," [%c]",(bbp->frame>0 ?'r':'f'));

  if (m_msg->srelv == 1) fprintf (fp, " %4d", bbp->score[pst.score_ix]);
  else if (m_msg->srelv > 0) fprintf (fp, " %4d", bbp->score[0]);

  if (m_msg->srelv > 1) fprintf (fp, " %4d", bbp->score[1]);
  if (m_msg->srelv > 2 || m_msg->stages>1) fprintf (fp, " %4d", bbp->score[2]);
  if (pst.zsflag>=0) {
    if (m_msg->z_bits==1)
      fprintf (fp, " %4.0f %7.2lg",zs_to_bit(bbp->zscore,n0,bbp->n1),bbp->escore);
    else
      fprintf (fp, " %6.1f %7.2lg",bbp->zscore,bbp->escore);
  }
  if (m_msg->markx == 6) fprintf(fp," <A HREF=\"#%s\">align</A>",l_name);
  else if (m_msg->markx == 9) {
    /* this should be unnecessary because it is done earlier */
    /* cal_coord(n0,n1,m_msg->sq0off,loffset+l_off-1,&(m_msg->aln)); */
    fprintf(fp,"\t%5.3f %5.3f %4d %4d %4ld %4ld %4ld %4ld %4ld %4ld %4ld %4ld %3d %3d %3d",
	    percent/100.0,gpercent/100.0, sw_score,lc,
	    m_msg->aln.d_start0,m_msg->aln.d_stop0,
	    m_msg->sq0off, m_msg->sq0off+m_msg->n0-1,
	    m_msg->aln.d_start1,m_msg->aln.d_stop1,
	    loffset+l_off, loffset+l_off+bbp->n1-1,
	    m_msg->aln.ngap_q,m_msg->aln.ngap_l,m_msg->aln.nfs);
  }
  fprintf (fp, "\n");
  fflush(fp);
  }

  if (quiet==0) {
    printf(" More scores? [0] ");
    fflush(stdout);
    if (fgets(rline,20,stdin)==NULL) exit(0);
    ntmp = 0;
    if (rline[0]!='\n' && rline[0]!=0) sscanf(rline,"%d",&ntmp);
    if (ntmp<=0) ntmp = 0;
    if (ntmp>0) {
      istart = istop;
      nshow += ntmp;
      goto l1;
    }
  }
  else if (quiet == 1)
    if (ib < nbest && (pst.zsflag>=0 && bbp->escore < m_msg->e_cut)) {
      if (m_msg->mshow_flg && istop >= m_msg->mshow) goto done;
      istart=istop;
      nshow += 10;
      goto l1;
    }

 done:
  m_msg->nshow = nshow;
  if (m_msg->markx==6) fprintf(fp,"</pre></tt><p><hr><p>\n");
  if (fp!=stdout) fprintf(fp,"\n");
}

/*
  q[] has one set of sfnums, 0 terminated
  s[] has second
  return first match or 0
*/
